import time
from Autotests.LocalMachine.Pages.BasePage import BaseWebPage
from Autotests.LocalMachine.Pages.BaseDialog import BaseWebDialog
from Autotests.LocalMachine.UiObjectsMap.AirClient import MainFrame, Backup, Dialog
from Autotests.LocalMachine.Controls.BaseControl import WebFindKey, BaseWebControl
from Autotests.LocalMachine.Controls.CheckBox import WebHorizontalCheckBox
from Autotests.LocalMachine.Controls.Button import WebButton
from Autotests.LocalMachine.Controls.ListView import WebListView
from Autotests.LocalMachine.Controls.TreeView import WebTreeView
from Autotests.LocalMachine.Controls.BaseView import BaseWebViewDelegate, BaseWebViewDelegateBuilder,\
    BaseWebViewLeafDelegate
from Autotests.LocalMachine.Controls.ProgressBar import BackupRestoreProgressBar
from Autotests.WebDriver import DRIVER


class BackupPlugins(object):
    filesystem = "FileSystem"
    vssSystemState = "VssSystemState"
    vssExchange = "VssExchange"
    networkShares = "NetworkShares"
    vssMsSql = "VssMsSql"
    mySql = "MySql"


class BackupTree(BaseWebDialog):
    def __init__(self):
        super(BackupTree, self).__init__()
        self._backupTreeView = WebTreeView(Backup.backupTree)

    def save(self):
        WebButton(Dialog.btnSaveFileTreeDialog).click()

    def cancel(self):
        WebButton(Dialog.btnCancelFileTreeDialog).click()

    def tree(self):
        return self._backupTreeView

    def goToHomeLocation(self):
        pass  # do nothing

    def deselectAll(self):
        self.tree().deselectAll()

    @BaseWebDialog.setter
    def makeSelection(self, path):
        self.deselectAll()
        self.tree().setItemSelection(path, True)


class WebBackupPluginDelegate(BaseWebViewLeafDelegate):
    def __init__(self, handler, index):
        super(WebBackupPluginDelegate, self).__init__(handler, index)
        self._enableCheckBox = WebHorizontalCheckBox(self.waitChildControl(*Backup.BackupList.pluginCheckbox))
        self._backupTree = BackupTree()
        self._loadingTimeoutSec = 7

    def waitForLoading(self):
        self.waitFor(lambda x: not BaseWebControl(Backup.BackupList.pluginLoader).isExists(1),
                     self._loadingTimeoutSec, 'plugin loading is too long...')

    def setSelection(self, selection):
        self._enableCheckBox.setCheckState(selection)
        self.waitForLoading()

    def isSelected(self):
        return self._enableCheckBox.isChecked()

    def plugin(self):
        return self._enableCheckBox.description()

    def backupTree(self):
        if not self._backupTree.isExists(timeoutSec=3):
            #WebButton(self.waitChildControl(WebFindKey.TAG_NAME, 'a')).click()
            self.setSelection(False)
            self.setSelection(True)
        time.sleep(1)
        return self._backupTree

    def isBackupTreeVisible(self):
        return self._backupTree.isExists() and self._backupTree.isVisible()

    def settingsIconClick(self):
        if not self.isSelected():
            DRIVER().actionChains().move_to_element(BaseWebControl(MainFrame.btnBackup)).perform()
            DRIVER().actionChains().move_to_element(self).perform()
            if not BaseWebControl((WebFindKey.XPATH, './/a[@class="icon"]')).isExists(2):
                print 'try to click icon again'
                DRIVER().actionChains().move_to_element(BaseWebControl(MainFrame.btnBackup)).perform()
                DRIVER().actionChains().move_to_element(self).perform()
        BaseWebControl(self.waitChildControl(WebFindKey.XPATH, './/a[@class="icon"]')).click()


class WebBackupListDelegate(BaseWebViewDelegate):
    def __init__(self, handler, index, childrenBuilder):
        super(WebBackupListDelegate, self).__init__(handler, index, childrenBuilder)

    def children(self):
        return filter(lambda x: isinstance(x, WebBackupPluginDelegate), super(self.__class__, self).children())


class BackupDelegateBuilder(BaseWebViewDelegateBuilder):
    def build(self, handler, index):
        if not index.isValid():
            return WebBackupListDelegate(handler, index, self)
        elif handler.hasChilds():
            return WebBackupPluginDelegate(handler, index)
        return BaseWebControl(handler)


class WebBackupPage(BaseWebPage):
    def __init__(self):
        super(WebBackupPage, self).__init__(Backup.backupPage)
        self._homeButton = WebButton(MainFrame.btnBackup)
        self._pluginList = WebListView(Backup.backupListView, BackupDelegateBuilder())
        self._startBackupButton = WebButton(MainFrame.btnRunBackup)
        self._backupProgressBar = BackupRestoreProgressBar()
        self._loadingTimeoutSec = 10

    def _getPluginDelegate(self, plugin):
        return self._pluginList.itemsFor(lambda x: x.plugin() == plugin)[0]

    def goToHomeLocation(self):
        super(WebBackupPage, self).goToHomeLocation()
        self._homeButton.click()

    def waitForLoading(self):
        self.waitFor(lambda x: not BaseWebControl(MainFrame.formLoader).isVisible(),
                     self._loadingTimeoutSec, 'loading is too long...')

    def waiter(func):
        def _decorator(self, *args, **kwargs):
            self.waitForLoading()
            return func(self, *args, **kwargs)
        return _decorator

    def setPluginEnabled(self, plugin, enabled):
        self._pluginList.transformItems(lambda x: x.plugin() == plugin,
                                        lambda x: x.setSelection(enabled))

    def getPluginsList(self):
        return [item.plugin for item in self._pluginList.items()]

    @BaseWebPage.setter
    def makeSelection(self, path, plugin):
        self._pluginList.deselectAll()
        backupPlugin = self._getPluginDelegate(plugin)
        backupPlugin.setSelection(True)
        backupPlugin.backupTree().deselectAll()
        backupPlugin.backupTree().makeSelection(path)

    def startBackup(self, path, plugin):
        self.makeSelection(path, plugin)
        time.sleep(5)  # wait button update
        self._startBackupButton.click()

    def waitForBackupComplete(self, timeout=20 * 60):
        self._backupProgressBar.performWait(timeout, message="Backup perform timeout")

    def performBackup(self, path, plugin, timeout=20 * 60):
        self.startBackup(path, plugin)
        self.waitForBackupComplete(timeout)

    def isPluginEnabledImpl(self, plugin):
        return self._getPluginDelegate(plugin).isSelected()

    @BaseWebPage.getter
    def isPluginEnabled(self, plugin):
        return self.isPluginEnabledImpl(plugin)

    def selectPlugin1(self, plugin):
        backupPlugin = self._getPluginDelegate(plugin)
        p = backupPlugin.backupTree()
        if backupPlugin.isBackupTreeVisible():
            p.cancel()
            return True
        else:
            return False

    @waiter
    def selectPlugin(self, plugin):
        backupPlugin = self._getPluginDelegate(plugin)
        backupPlugin.setSelection(False)
        backupPlugin.setSelection(True)
        return self.setupDialogIsVisible(plugin)

    def setupDialogIsVisible(self, plugin):
        self.waitForLoading()
        backupPlugin = self._getPluginDelegate(plugin)
        if plugin == BackupPlugins.filesystem or plugin == BackupPlugins.vssExchange or plugin == BackupPlugins.vssMsSql:
            isVisible = self.waitFor(lambda x: backupPlugin.isBackupTreeVisible(),
                                     self._loadingTimeoutSec, 'waiting for backup tree')
            time.sleep(1)
            backupPlugin.backupTree().cancel()
        elif plugin == BackupPlugins.networkShares or plugin == BackupPlugins.mySql:
            dialog = BaseWebControl((WebFindKey.XPATH, '//div[@role="dialog"]/div[@id="plugins-config-container"]'))
            time.sleep(1)
            isVisible = dialog.isVisible()
            WebButton((WebFindKey.XPATH, ".//div[@id='plugins-config-container']//button[@name='cancel']"))
        if isVisible:
            return True
        else:
            return False

    @waiter
    def selectPluginByIconClick(self, plugin):
        backupPlugin = self._getPluginDelegate(plugin)
        backupPlugin.setSelection(False)
        backupPlugin.settingsIconClick()
        return self.setupDialogIsVisible(plugin)
